package com.leyou.service;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.leyou.auth.entity.UserInfo;
import com.leyou.client.GoodsClient;
import com.leyou.common.utils.JsonUtils;
import com.leyou.interceptor.LoginInterceptor;
import com.leyou.item.pojo.Sku;
import com.leyou.pojo.Cart;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
public class CartService {

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private GoodsClient goodsClient;

    // 定义redis里储存购物车数据的前缀
    private static final String KEY_PREFIX = "leyou:cart:uid:";

    public void addCart(Cart cart) {
        // 从ThreadLocal线程域里获取登录的用户
        UserInfo userInfo = LoginInterceptor.getUserInfo();
        String key = KEY_PREFIX + userInfo.getId();  // 获取需要储存到redis里的key，用户id

        // 根据用户id从redis里获取这个用户的购物车数据。hash操作对象。
        BoundHashOperations<String, Object, Object> hashOps = this.redisTemplate.boundHashOps(key);

        Long skuId = cart.getSkuId();  // 需要加购物车的商品ID
        Integer num = cart.getNum();   // 需要加购物车的商品数量

        // 操作redis,根据商品id查该商品是否存在,根据传过来的cart
        Boolean boo = hashOps.hasKey(skuId.toString());

        if (boo) {
            // 如果购物车里有存在,获取购物车数据。加上数量
            String json = Objects.requireNonNull(hashOps.get(skuId.toString())).toString();
            cart = JsonUtils.parse(json, Cart.class);  // 使用工具类序列化成cart对象，重新赋值给cart对象。
            cart.setNum(cart.getNum() + num); // 更新购物车的数量

        } else {
            // 如果购物车没有不存在，相当于重新封装数据
            cart.setUserId(userInfo.getId());   // 设置用户id
            Sku sku = this.goodsClient.querySkuById(skuId);
            cart.setImage(StringUtils.isBlank(sku.getImages()) ? "" : StringUtils.split(sku.getImages(), ",")[0]);
            cart.setPrice(sku.getPrice());
            cart.setTitle(sku.getTitle());
            cart.setOwnSpec(sku.getOwnSpec());
        }
        // 不管结果如何，数据写入redis,修改和新增都一样
        hashOps.put(cart.getSkuId().toString(), Objects.requireNonNull(JsonUtils.serialize(cart)));

    }

    // 已登录状态下查询购物车,展示到购物车页面
    public List<Cart> queryCartList() {
        // 从ThreadLocal线程域里获取登录的用户
        UserInfo userInfo = LoginInterceptor.getUserInfo();

        // 获取redis里的用户的key值
        String key = KEY_PREFIX + userInfo.getId();
        if (!this.redisTemplate.hasKey(key)) {
            // 如果不存在,直接返回
            return null;
        }
        BoundHashOperations<String, Object, Object> hashOps = this.redisTemplate.boundHashOps(key);
        List<Object> carts = hashOps.values(); // 使用values方法获取值
        if (CollectionUtils.isEmpty(carts)) {
            return null;
        }

        // 如果有数据 查询购物车的数据并且返回,使用工具类把字符串转成对象
        return carts.stream().map(c -> JsonUtils.parse(c.toString(), Cart.class)).collect(Collectors.toList());

    }

    // 加减商品数量
    public void updateCart(Cart cart) {
        UserInfo userInfo = LoginInterceptor.getUserInfo();
        String key = KEY_PREFIX + userInfo.getId();
        // 获取hash操作对象
        BoundHashOperations<String, Object, Object> hashOps = this.redisTemplate.boundHashOps(key);

        // 获取商品信息
        String json = Objects.requireNonNull(hashOps.get(cart.getSkuId().toString())).toString();
        Cart newCart = JsonUtils.parse(json, Cart.class);  // 获取购物车对象newCart

        newCart.setNum(cart.getNum());  // 把新的数量赋值给获取到的购物车对象,更新数量
        hashOps.put(cart.getSkuId().toString(), Objects.requireNonNull(JsonUtils.serialize(newCart)));  // 把新的newCart购物车对象重新放到redis里


    }

    // 删除商品的方法
    public void deleteCart(String skuId) {
        UserInfo userInfo = LoginInterceptor.getUserInfo();
        String key = KEY_PREFIX + userInfo.getId();
        // 获取hash操作对象
        BoundHashOperations<String, Object, Object> hashOps = this.redisTemplate.boundHashOps(key);
        hashOps.delete(skuId);  // 直接删除

    }

    public List<Cart> mergeCartList(String carts) {
        // 从ThreadLocal线程域里获取登录的用户
        UserInfo userInfo = LoginInterceptor.getUserInfo();

        // 获取redis里的用户的key值
        String key = KEY_PREFIX + userInfo.getId();

        // 根据用户id从redis里获取这个用户的购物车数据。hash操作对象。
        BoundHashOperations<String, Object, Object> hashOps = this.redisTemplate.boundHashOps(key);


        // 数据接收
        List<Cart> cartLists = JsonUtils.parseList(carts, Cart.class);
        if (!CollectionUtils.isEmpty(cartLists)) {
            for (Cart cart : cartLists) {
                Long skuId = cart.getSkuId();
                Integer num = cart.getNum();
                Boolean boo = hashOps.hasKey(skuId.toString()); //看看传过来的商品id是否存在这个redis里
                if (boo) {
                    // 如果存在加数量合并就行了
                    String json = Objects.requireNonNull(hashOps.get(skuId.toString())).toString();
                    cart = JsonUtils.parse(json, Cart.class);  // 使用工具类序列化成cart对象，重新赋值给cart对象。
                    cart.setNum(cart.getNum() + num); // 更新购物车的数量
                } else {
                    // 如果不存在封装数据放到redis里
                    cart.setUserId(userInfo.getId());   // 设置用户id
                    Sku sku = this.goodsClient.querySkuById(skuId); // 获取sku数据,封装数据
                    cart.setImage(StringUtils.isBlank(sku.getImages()) ? "" : StringUtils.split(sku.getImages(), ",")[0]);
                    cart.setPrice(sku.getPrice());
                    cart.setTitle(sku.getTitle());
                    cart.setOwnSpec(sku.getOwnSpec());
                }
                // 不管结果如何，数据写入redis,修改和新增都一样
                hashOps.put(cart.getSkuId().toString(), Objects.requireNonNull(JsonUtils.serialize(cart)));
            }
        }

        List<Object> mergeCarts = hashOps.values(); // 使用hashOps的values方法获取这个用户合并后的所有数据

        // 和上面的方式一样,把每组json对象封装成对象返回
        return mergeCarts.stream().map(c -> JsonUtils.parse(c.toString(), Cart.class)).collect(Collectors.toList());
    }
}